#include "button.hpp"

//#include <iostream>
#include <stdio.h>
void LOG_ID(int num){printf("%d",num);}
void LOG(const char* str) { printf("INFO:%s\r\n",str); }
uint16_t Button::getInterval(){return TICKS_INTERVAL;}
bool Button::register_callback(const callback_t callback,
                               const PressEvent event) {
  switch (event) {
    case Button::PressEvent::PRESS_SINGLE:
      this->callback[PRESS_SINGLE - 1] = callback;
      break;
    case Button::PressEvent::PRESS_DOUBLE:
      this->callback[PRESS_DOUBLE - 1] = callback;
      break;
    case Button::PressEvent::PRESS_LONG_START:
      this->callback[PRESS_LONG_START - 1] = callback;
      break;
    case Button::PressEvent::PRESS_LONG_HOLD:
      this->callback[PRESS_LONG_HOLD - 1] = callback;
      break;
    default:
      return false;
      break;
  }
  return true;
}

void Button::tick_handler() {
  // 读取按键电平
  bool pin_level = read_Pin();
  uint16_t interval = getInterval();
  /*------------消抖---------------*/
  if (pin_level != this->pin) {
    debounce_cnt++;
    if (debounce_cnt >= DEBOUNCE_TICKS) {
      this->pin = pin_level;
      debounce_cnt = 0;
    }
  } else {
    debounce_cnt = 0;
  }
  /*--------------状态机-------------*/
  switch (this->state) {
    case Button::State::None_Press:
      if (this->pin == active_level) {             // 按键按下
        this->state = Button::State::First_Press;  // 初次按下
				LOG_ID(this->buttonId);
        LOG(":First_Press");
      } else {
        this->event = Button::PressEvent::NONE_PRESS;  // 无按键事件
      }
      /* code */
      break;
    case Button::State::First_Press:
      if (this->pin == active_level) {  // 按键按下
        this->ticksTime += interval;
        if (this->ticksTime >= LONG_INTERVAL) {
          this->ticksTime = 0;
          this->state = Button::State::Long_Press;  // 长按
          this->event = Button::PressEvent::PRESS_LONG_START;
          if (this->callback[PRESS_LONG_START - 1] != nullptr) {
            this->callback[PRESS_LONG_START - 1]();
          }
					LOG_ID(this->buttonId);
          LOG("Long_Press_Start");
        }
      } else {  // 按键松开
        if (this->ticksTime >=
            SHORT_INTERVAL) {  // 按下时间大于短按时间，但小于长按时间，触发单击
          this->ticksTime = 0;
          this->state = Button::State::Single_Check;  // 单击检测
          this->event = Button::PressEvent::PRESS_SINGLE;
          if (this->callback[PRESS_SINGLE - 1] != nullptr) {
            this->callback[PRESS_SINGLE - 1]();
          }
					LOG_ID(this->buttonId);
          LOG("Single_Check");
        } else {  // 按下时间小于短按时间，不触发单击，进入双击检测
          this->ticksTime = 0;
          this->state = Button::State::Press_Check;  // 连击检测
        }
      }
      break;
    case Button::State::Press_Check:
      if (this->pin != active_level) {  // 按键松开
        this->ticksTime += interval;
        if (this->ticksTime >= SHORT_INTERVAL / 2) {
          this->ticksTime = 0;
          this->state = Button::State::Single_Check;  // 单击
          this->event = Button::PressEvent::PRESS_SINGLE;
          if (this->callback[PRESS_SINGLE - 1] != nullptr) {
            this->callback[PRESS_SINGLE - 1]();
          }
					LOG_ID(this->buttonId);
          LOG("Single_Check");
        }
      } else  // 在SHORT_INTERVAL/2时间内再次按下
      {
        this->ticksTime = 0;
        this->state = Button::State::Double_Check;  // 双击
        this->event = Button::PressEvent::PRESS_DOUBLE;
        if (this->callback[PRESS_DOUBLE - 1] != nullptr) {
          this->callback[PRESS_DOUBLE - 1]();
        }
				LOG_ID(this->buttonId);
        LOG("Double_Check");
      }
      break;
    case Button::State::Single_Check:
      this->state = Button::State::None_Press;  // 无按键
      this->event = Button::PressEvent::NONE_PRESS;
      break;
    case Button::State::Double_Check:
      if (this->pin != active_level) {
        this->state = Button::State::None_Press;  // 无按键
        this->event = Button::PressEvent::NONE_PRESS;
      }
      break;
    case Button::State::Long_Press:
        if(this->pin != active_level){//松开
            this->state = Button::State::None_Press;  // 无按键
            this->event = Button::PressEvent::NONE_PRESS;
        }else{
            this->ticksTime += interval;
            if (this->ticksTime >= SHORT_INTERVAL) {
                this->ticksTime = 0;
                this->event = Button::PressEvent::PRESS_LONG_HOLD;
                if (this->callback[PRESS_LONG_HOLD - 1] != nullptr) {
                    this->callback[PRESS_LONG_HOLD - 1]();
                }
								LOG_ID(this->buttonId);
                LOG("Long_Press_Hold");
            }
        }
        break;
    default:
			LOG_ID(this->buttonId);
    LOG("error");
      break;
  }
}
